#!/bin/python3
# -*- coding: UTF-8
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.colors
import matplotlib.dates as mdates
from matplotlib.ticker import ScalarFormatter
from matplotlib.ticker import LogFormatter
from matplotlib.ticker import MultipleLocator
from matplotlib.ticker import FormatStrFormatter
from matplotlib.font_manager import findfont, FontProperties  
import matplotlib.font_manager as font_manager
import matplotlib.ticker as mtick

import seaborn as sns

sns.set_theme(style="ticks", font_scale=1.33)
sns.set_context("paper", font_scale=1.5)
plt.rcParams['xtick.direction'] = 'in'#将x的刻度线方向设置向内
plt.rcParams['ytick.direction'] = 'in'#将y的刻度方向设置向内
plt.rcParams['font.family']=['Sarasa Mono SC'] #用来正常显示中文标签
txt_workloads = ""
txt_executiontime = "执行时间(按ccsync归一化)"

plt.rcParams['axes.xmargin'] = 0

bench_list1 = ['barnes', 'raytrace_teapot', 'raytrace_car']
bench_list2 = ['sh8', 'larson', 'xmalloc']

bencn_baseline1 = 'ccsync'
bencn_baseline2 = 'ccsync'
hatch_list = ['cacccsyn', 'cacdsmsyn', 'cachsyn', 'cacflat', 'cacsffwd'] 
# TODO: 色表修改
color_base_max = 0.9


colortbls = [	
		(color_base_max * 14.0/14.0,  color_base_max* 14.0/14.0, color_base_max*14.0/14.0), 
		(color_base_max * 13.0/14.0,  color_base_max* 13.0/14.0, color_base_max*13.0/14.0), 
		(color_base_max * 12.0/14.0,  color_base_max* 12.0/14.0, color_base_max*12.0/14.0), 
		(color_base_max * 11.0/14.0,  color_base_max* 11.0/14.0, color_base_max*11.0/14.0), 
		(color_base_max * 10.0/14.0,  color_base_max* 10.0/14.0, color_base_max*10.0/14.0),
		(color_base_max * 9.0/14.0,  color_base_max* 9.0/14.0, color_base_max*9.0/14.0),
		(color_base_max * 8.0/14.0,  color_base_max* 8.0/14.0, color_base_max*8.0/14.0),
		(color_base_max * 7.0/14.0,  color_base_max* 7.0/14.0, color_base_max*7.0/14.0),
		(color_base_max * 6.0/14.0,  color_base_max* 6.0/14.0, color_base_max*6.0/14.0),
		(color_base_max * 5.0/14.0,  color_base_max* 5.0/14.0, color_base_max*5.0/14.0),
		(color_base_max * 4.0/14.0,  color_base_max* 4.0/14.0, color_base_max*4.0/14.0),
		(color_base_max * 3.0/14.0,  color_base_max* 3.0/14.0, color_base_max*3.0/14.0),
		(color_base_max * 2.0/14.0,  color_base_max* 2.0/14.0, color_base_max*2.0/14.0),
		(color_base_max * 1.0/14.0,  color_base_max* 1.0/14.0, color_base_max*1.0/14.0),
		(color_base_max * 0.0/14.0,  color_base_max* 0.0/14.0, color_base_max*0.0/14.0)
		]
		
hatchtbls = ['']
		
# colortbls=[(0/255, 45/255, 106/255),(0x99/255, 0xc5/255,0x56/255), (0/255, 92/255, 171/255), (220/255, 176/255, 243/255), (255/255, 195/255, 37/255), (0xfd/255, 0xaf/255, 0xab/255),  (227/255, 67/255, 35/255),
# (0/255, 147/255, 43/255),(0x99/255, 0xa8/255,0x56/255), (0/255, 92/255, 121/255), (227/255, 27/255, 35/255)
# ]
cl_blk = (7/255,7/255,7/255,1)
time_column = 0
rss_column = 1

# y轴上限
avg_ylimit = 1
size_ylimit = 1

accuracy = 1

keynote_font = 9

#  搞一个数组,这里画了就+1
def autolabel(ax,rects, ylimit, rect_table):
	"""Attach a text label above each bar in *rects*, displaying its height."""
	t = 0
	for rect in rects:
		# print (rect)
		height = rect.get_height()
		#print(rect.get_height())
		top_height = 0.1
		if (rect.get_height()>=ylimit):
			# print(0 - (top_height * rect_table[t]))
			ax.annotate('{:.1f}x'.format(height),
						xy=(rect.get_x() + rect.get_width() / 2, -0.5 + (top_height * rect_table[t])),
						xytext=(0, 0),  # 3 points vertical offset
						fontsize=keynote_font
						,textcoords="offset points",
						ha='center', va='bottom')
			ax.vlines(x=rect.get_x() + rect.get_width() / 2, ymin= -0.5 + (top_height * (rect_table[t] + 1)), ymax=0, alpha=0.618, linewidth=0.5, linestyles='dashed', color = cl_blk)
			rect_table[t] += 1
			# print(rect_table)
		t+=1

# 读文件
def read_data(file_path):
	data = np.loadtxt(file_path,dtype=str,delimiter=' ')
	# print (data)
	return data

def get_bench_data(data, bench_name):
	ret = data[data[:, 0] == bench_name]
	# 裁减
	return ret

def __get_bench_data_x_y(data, bench_name):
	ret = get_bench_data(data, bench_name)
	x_name = ret[:, 1]
	y = ret[:, 2:]
	# print (y)
	return x_name, y

def get_bench_data_x_y(data, bench_name, column, typ):
	x_name, y = __get_bench_data_x_y(data, bench_name)
	x_num = np.unique(x_name).size
	x_name_row = int(x_name.size / x_num)
	x_name = x_name.reshape(x_name_row, x_num)

	# print (x_name)
	# print (y)
	y = y[:, column].astype(typ)
	y = np.array(y)

	y = y.reshape(x_name_row, x_num)
	# y.
	return x_name, np.mean(y, axis=0), np.std(y, axis=0)


def plot_subfig_avg(data_x, data_avg_y, data_std, axs, ylimit, benchline1):
	x_length = len(data_x)
			   # the label locations

	width = 0.75

	rel = np.where(data_x == benchline1)		 # use bencn_baseline
	rel = rel[0][0]

	# print (data_x[rel])
	# print (data_avg_y[0][rel])
	# print (np.true_divide(data_avg_y[0], data_avg_y[0][rel]))

	rects = []
	column = len(data_avg_y[:])
	x = np.arange(column)   
	

	div = 1 / (x_length + 1)
	medium = 1 / 2

	# print(data_x)
	# true_x = - width * (medium - (x + 1) * div)
	# print (true_x)
	# x[i] - width*(medium - (i + 1) * div)
	# print ( column)
	# print (column)
	# # print (data_x)
	# print (np.true_divide(data_avg_y[:,0], data_avg_y[:, rel]))
	color_cnt = 0
	for i in range(0, x_length):
		# axs.vlines(x=x-0.5 , ymin= -1, ymax=ylimit, linewidth=0.5, linestyles='dashed', alpha=0.618)
		# axs.vlines(x=x+0.5 , ymin= -1, ymax=ylimit, linewidth=0.5, linestyles='dashed',  alpha=0.618)
		# print (data_avg_y[i])
		# print (data_avg_y[:,i])
		# print ( np.true_divide(data_avg_y[:,i], data_avg_y[:, rel]))
		# 这是横着画的
		if data_x[i] in hatch_list:
			hatchval = 'xx'
			color = colortbls[(color_cnt - 1)%len(colortbls)]
		else:
			hatchval = hatchtbls[color_cnt%len(hatchtbls)]
			color = colortbls[color_cnt%len(colortbls)]
			color_cnt += 1
		print (data_x[i])
		print (np.true_divide(data_avg_y[:,i], data_avg_y[:, rel]) - 1)
		rects.append(axs.bar( x - width*(medium - (i + 1) * div), 
				np.true_divide(data_avg_y[:,i], data_avg_y[:, rel]) - 1, 
				width * div, 
					yerr = np.true_divide(data_std[:,i], data_avg_y[:, rel]), 
						label=data_x[i],
							color=color, 
								alpha=0.9, capsize=1, error_kw={"elinewidth" : 1, "alpha" : 0.8}, hatch=hatchval))
	return rects


def set_axs_label(axs, data_x, data_avg_y, rects, xlabel, ylabel, ybotlimit, ytoplimit, benchlist):
	x_length = len(data_x)
	column = len(data_avg_y)
	x = np.arange(column)
	
	axs.set_xlabel(xlabel)
	axs.set_ylabel(ylabel)
	#axs.set_title('Virtual Memory Claimed Size Ratio (vs Glibc) For X86')
	axs.set_xticks(x)
	axs.set_xticklabels(benchlist) #rotation=45)
	axs.yaxis.set_major_formatter(mtick.PercentFormatter(1.0))

	# 画横线区分
	idx = 0
	for xname in x:
		axs.hlines(y=0, xmin=x[idx]-0.4, xmax=x[idx]+0.4, linewidth=0.5, color = cl_blk)
		idx += 1
	# axs.hlines(y=0, xmin= x[0] - 0.5, xmax=x[len(x)-1]+ 0.5, linewidth=0.5, linestyles='dashdot')

	# axs.set_yscale("log")
	axs.set_ylim(ybotlimit ,ytoplimit)
	# y_major_locator=MultipleLocator(1)
	# axs.yaxis.set_major_locator(y_major_locator)
	# axs.yaxis.set_major_formatter(LogFormatter())
	rect_table = np.zeros(x_length)
	t=0
	for rect in rects:
		autolabel(axs, rect, ytoplimit, rect_table)
		t = t + 1
		# i+=1


def plot_x86_arm(data_x, data_avg_y, data_std, data_avg_y_arm, data_std_arm, xlabel, ylabel, ybotlimit, ytoplimit, benchlist, benchlist_arm, benchline1):
	# fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(12, 4))
	# # plt.xticks(rotation=120)
	# rects = plot_subfig_avg(data_x, data_avg_y, data_std, axs[0], ytoplimit, benchline1)
	# set_axs_label(axs[0], data_x, data_avg_y, rects, xlabel, ylabel, ybotlimit, ytoplimit, benchlist)
	# rects = plot_subfig_avg(data_x, data_avg_y_arm, data_std_arm, axs[1], ytoplimit, benchline1)
	# set_axs_label(axs[1], data_x, data_avg_y, rects, xlabel, ylabel, ybotlimit, ytoplimit, benchlist_arm)

	# 每张一个
	fig, axs = plt.subplots(nrows=1, ncols=1, figsize=(9, 3))
	# plt.xticks(rotation=120)
	rects = plot_subfig_avg(data_x, data_avg_y, data_std, axs, ytoplimit, benchline1)
	set_axs_label(axs, data_x, data_avg_y, rects, xlabel, ylabel, ybotlimit, ytoplimit, benchlist)

	plt.legend(loc='upper center', bbox_to_anchor=(0.46, -0.05), frameon=False, labelspacing=0.1, handletextpad=0.1, columnspacing=0.2, ncol= len(dx)/2)

	matplotlib.pyplot.subplots_adjust(left=0.08, right = 0.995, bottom = 0.22, top = 0.93, wspace = 0.10 )
	
	plt.savefig("./fig/"+"splash_x86.pdf", format = "pdf")

	fig, axs = plt.subplots(nrows=1, ncols=1, figsize=(9, 3))
	rects = plot_subfig_avg(data_x, data_avg_y_arm, data_std_arm, axs, ytoplimit, benchline1)
	set_axs_label(axs, data_x, data_avg_y, rects, xlabel, ylabel, ybotlimit, ytoplimit, benchlist_arm)
	plt.legend(loc='upper center', bbox_to_anchor=(0.46, -0.05), frameon=False, labelspacing=0.1, handletextpad=0.1, columnspacing=0.2, ncol= len(dx)/2)


	matplotlib.pyplot.subplots_adjust(left=0.08, right = 0.995, bottom = 0.22, top = 0.93, wspace = 0.10 )
	plt.savefig("./fig/"+"splash_arm.pdf", format = "pdf")
	# plt.tick_params(axis='y', which='minor')

	return fig, axs

def calculate_data(data, bench_list, column):
	ry = []
	ry_std = []

	for bench in bench_list:
		tx, ty, tstd = get_bench_data_x_y(data, bench, column, float)
		# print (tx, ty, tstd)
		ry.append(ty)
		ry_std.append(tstd)

	rx = tx[0]
	ry = np.array(ry)
	ry_std = np.array(ry_std)
	return rx, ry, ry_std




data = read_data('./splash_13700k.tsv')
data_arm = read_data('./splash_sdm888.tsv')
dx, dy, dy_std = calculate_data(data, bench_list1, 0)
adx, ady, ady_std = calculate_data(data_arm, bench_list1, 0)
# dx_arm, dy_arm, dy_std_arm = calculate_data(data_arm, arm_bench_list, 0)

# print (dx, dy, dy_std)
plot_x86_arm(dx, dy, dy_std, ady, ady_std, txt_workloads, txt_executiontime, -0.5, size_ylimit, bench_list1, bench_list1, bencn_baseline1)

# plt.legend(loc='upper center', bbox_to_anchor=(0, 1.15), frameon=False, ncol= round((len(dx))/2))

# plt.legend(loc='upper center', frameon=False, ncol= round((len(dx))/2))


# avg
# data = read_data('./membench.tsv')
# data_arm = read_data('./arm_membench.tsv')
# dx, dy, dy_std = calculate_data(data, bench_list2, 0)
# adx, ady, ady_std = calculate_data(data_arm, bench_list2, 0)
# print (dx, dy, dy_std)
# plot_x86_arm(dx, dy, dy_std, ady, ady_std, 'Workloads', 'Execution Time (Normalized to ccsynch)', -1, 2*size_ylimit, bench_list2, bench_list2, bencn_baseline2)



# plt.legend(loc='upper center',  frameon=False, ncol= round((len(dx))/2))

# dx, dy, dy_std = calculate_data(data, bench_list, 0)
# dx_arm, dy_arm, dy_std_arm = calculate_data(data_arm, arm_bench_list, 0)

# # print (alldatay)
# # print (all_data_x[0])
# # 绘制平均性能图
# # plot_x86_arm(dx, dy, dy_std, dy, dy_std, 'xzvxz', 'xzvczxX', 0.2, avg_ylimit)


# fig, axs = plot_x86_arm(dx, dy, dy_std, dy_arm, dy_std_arm, '测试负载', '执行时间(相对wfslab)', -1, avg_ylimit, bench_list, arm_bench_list)
# # for axsi in axs:
#	 # axsi.set_yscale("symlog")
#	 # axsi.yaxis.set_major_formatter(LogFormatter())
#	 # axsi.yaxis.set_minor_formatter(FormatStrFormatter("%.1f"))
#	 # y_major = matplotlib.ticker.LogLocator(base = 10, numticks = 10)
#	 # axsi.yaxis.set_major_locator(y_major)


# plt.legend(loc='upper center', bbox_to_anchor=(0, 1.15), frameon=False, ncol= len(dx))
# # plt.show()

# alldata_sizey = []
# alldata_sizey_std = []

# # 绘制RSS图
# dx, dy, dy_std = calculate_data(data, bench_list,  1)
# dx_arm, dy_arm, dy_std_arm = calculate_data(data_arm, arm_bench_list, 1)

# fig, axs = plot_x86_arm(dx, dy, dy_std, dy_arm, dy_std_arm, '测试负载', 'RSS大小(相对wfslab)', -1, size_ylimit, bench_list, arm_bench_list)

# y_major_locator=MultipleLocator(1)
# for axsi in axs:
#	 axsi.yaxis.set_major_locator(y_major_locator)

# 绘制WCET图F



# 绘制OBJ_SIZE


# plt.legend(bbox_to_anchor=(0.4, 1.15), frameon=False, ncol= len(dx))
# #plt.tight_layout()
plt.show()